package br.com.cfccultura.admin.model.dao.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import br.com.cfccultura.admin.model.dao.IAgendamentoProvaDAO;
import br.com.cfccultura.admin.model.dao.IBancoDAO;
import br.com.cfccultura.admin.model.dao.IOrdemServicoDAO;
import br.com.cfccultura.admin.model.dao.IServicoDAO;
import br.com.cfccultura.admin.model.dao.ITurmaDAO;
import br.com.cfccultura.admin.model.enums.FormaPagamento;
import br.com.cfccultura.admin.model.enums.TipoCurso;
import br.com.cfccultura.admin.model.vo.Aluno;
import br.com.cfccultura.admin.model.vo.DirecionamentoCheque;
import br.com.cfccultura.admin.model.vo.Funcionario;
import br.com.cfccultura.admin.model.vo.Matricula;
import br.com.cfccultura.admin.model.vo.OrdemServico;
import br.com.cfccultura.admin.model.vo.OrdemServicoEspecie;
import br.com.cfccultura.admin.model.vo.OrdemServicoItem;

@Repository
public class OrdemServicoDAO extends DAO implements IOrdemServicoDAO {
	
	@Autowired
	private ITurmaDAO turmaDAO;
	@Autowired
	private IAgendamentoProvaDAO agendamentoProvaDAO;
	@Autowired
	private IServicoDAO servicoDAO;
	@Autowired
	private IBancoDAO bancoDAO;
	
	@Override
	public OrdemServico consultar(Integer codigo) {
		return consultar(codigo, true, true);
	}	
	
	@Override
	public OrdemServico consultar(final Integer codigo, Boolean carregaEspecie, Boolean carregaItem) {
		String sql = "SELECT cd_aluno, vl_total, dt_cadastro, cd_funcionario_cadastro FROM tb_ordem_servico WHERE cd_ordem_servico = ?";
		OrdemServico os = queryForObject(sql, new Object[] {codigo}, new RowMapper<OrdemServico>() {
			@Override
			public OrdemServico mapRow(ResultSet rs, int arg1) throws SQLException {
				OrdemServico vo = new OrdemServico();
				vo.setCodigo(codigo);
				vo.setAluno(new Aluno(rs.getInt("cd_aluno")));
				vo.setTotal(rs.getDouble("vl_total"));
				vo.setCadastro(rs.getDate("dt_cadastro"));
				vo.setUsuarioSistema(new Funcionario(rs.getInt("cd_funcionario_cadastro")));
				return vo;
			}			
		});
			
		if(carregaItem)
			os.setItems(consultarItens(codigo));
		
		if(carregaEspecie) {
			OrdemServicoEspecie especie = new OrdemServicoEspecie();
			especie.setOrdemServico(os);
			os.setEspecies(consultarEspecies(especie));
		}
		
		return os;
	}
	
	@Override
	public List<OrdemServicoItem> consultarItens(Integer ordemServico) {
		String sql = "SELECT cd_ordem_servico_item, cd_servico, cd_turma_matricula, cd_agendamento_prova, qt_servico, vl_venda, vl_custo, id_tipo_curso FROM tb_ordem_servico_item WHERE cd_ordem_servico = ?";
		List<OrdemServicoItem> itens = query(sql, new Object[] {ordemServico}, new RowMapper<OrdemServicoItem>() {
			@Override
			public OrdemServicoItem mapRow(ResultSet rs, int arg1) throws SQLException {
				OrdemServicoItem vo = new OrdemServicoItem();
				vo.setCodigo(rs.getInt("cd_ordem_servico_item"));
				if(rs.getObject("cd_servico") != null)
					vo.setServico(getServicoDAO().consultar(rs.getInt("cd_servico")));
				if(rs.getObject("cd_turma_matricula") != null) {
					vo.setMatricula(getTurmaDAO().consultarMatricula(new Matricula(rs.getInt("cd_turma_matricula"))));
				}
				if(rs.getObject("cd_agendamento_prova") != null) {
					vo.setAgendamentoProva(getAgendamentoProvaDAO().consultar(rs.getInt("cd_agendamento_prova")));
				}
				vo.setQtde(rs.getInt("qt_servico"));
				vo.setValorVenda(rs.getDouble("vl_venda"));
				vo.setValorCusto(rs.getDouble("vl_custo"));
				if(rs.getObject("id_tipo_curso") != null)
					vo.setTipoCurso(TipoCurso.setValue(rs.getInt("id_tipo_curso")));
				return vo;
			}			
		});	
		return itens;
	}
	
	@Override
	public List<OrdemServicoEspecie> consultarEspecies(OrdemServicoEspecie vo) {
		String sql = "SELECT cd_ordem_servico, cd_ordem_servico_especie, id_tipo_especie, vl_especie, cd_banco, dc_cheque_agencia, dc_cheque_conta, dc_cheque_numero, dt_cheque " +
				"FROM tb_ordem_servico_especie " +
				"WHERE 1 = 1 ";
		List<Object> params = new ArrayList<Object>();
		
		if(vo.getOrdemServico() != null && vo.getOrdemServico().getCodigo() != null) {
			sql += " and cd_ordem_servico = ? ";
			params.add(vo.getOrdemServico().getCodigo());
		}
		if(vo.getCodigo() != null) {
			sql += " and cd_ordem_servico_especie = ? ";
			params.add(vo.getCodigo());
		}
		
		List<OrdemServicoEspecie> especies = query(sql, params.toArray(), new RowMapper<OrdemServicoEspecie>() {
			@Override
			public OrdemServicoEspecie mapRow(ResultSet rs, int arg1) throws SQLException {
				OrdemServicoEspecie vo = new OrdemServicoEspecie();
				vo.setCodigo(rs.getInt("cd_ordem_servico_especie"));
				vo.setFormaPagamento(FormaPagamento.setValue(rs.getInt("id_tipo_especie"))); 
				vo.setValor(rs.getDouble("vl_especie"));
				if(rs.getObject("cd_banco") != null) {
					vo.setBanco(getBancoDAO().consultar(rs.getInt("cd_banco")));
					vo.setAgencia(rs.getString("dc_cheque_agencia"));
					vo.setConta(rs.getString("dc_cheque_conta"));
					vo.setCheque(rs.getString("dc_cheque_numero"));
					vo.setDataCheque(rs.getDate("dt_cheque"));
				}
				
				vo.setOrdemServico(new OrdemServico(rs.getInt("cd_ordem_servico")));
				return vo;
			}			
		});
		return especies;
	}
	
	@Override
	public OrdemServicoEspecie consultarEspecie(Integer codigo) {
		List<OrdemServicoEspecie> especies = consultarEspecies(new OrdemServicoEspecie(codigo));
		if(especies.size() > 0)
			return especies.get(0);
		throw new RuntimeException("Codigo de OrdemServicoEspecie invalido -> " + codigo);
	}
	
	@Override
	public void incluir(final OrdemServico vo) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		update(new PreparedStatementCreator() {			
			@Override
			public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
				String sql = "INSERT INTO tb_ordem_servico(cd_aluno, vl_total, dt_cadastro, cd_funcionario_cadastro) values(?,?,?,?)";
				PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

				ps.setObject(1, vo.getAluno() != null ? vo.getAluno().getCodigo() : null);
				ps.setDouble(2, vo.getTotal());
				ps.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()));
				ps.setInt(4, vo.getUsuarioSistema().getCodigo());	 
			    return ps;
			}
		}, keyHolder);
		
		vo.setCodigo(keyHolder.getKey().intValue());
		for(OrdemServicoItem item : vo.getItems()) {
			incluirItem(vo.getCodigo(), item);
		}
		
		for(OrdemServicoEspecie especie : vo.getEspecies()) {
			incluirEspecie(vo.getCodigo(), especie);
		}
	}
	
	@Override
	public void incluirItem(final Integer codigo, final OrdemServicoItem vo) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		update(new PreparedStatementCreator() {			
			@Override
			public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
				String sql = "INSERT INTO tb_ordem_servico_item(cd_ordem_servico, cd_servico, cd_turma_matricula, cd_agendamento_prova, qt_servico, vl_venda, vl_custo, id_tipo_curso) values(?,?,?,?,?,?,?,?)";
				PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

				ps.setInt(1, codigo);
				ps.setObject(2, vo.getServico() != null ? vo.getServico().getCodigo() : null);
				ps.setObject(3, vo.getMatricula() != null ? vo.getMatricula().getCodigo() : null);
				ps.setObject(4, vo.getAgendamentoProva() != null ? vo.getAgendamentoProva().getCodigo() : null);
				ps.setInt(5, vo.getQtde());
				ps.setDouble(6, vo.getValorVenda());
				ps.setDouble(7, vo.getValorCusto());
				ps.setObject(8, vo.getTipoCurso() != null ? vo.getTipoCurso().getValue() : null);
				
			    return ps;
			}
		}, keyHolder);
		vo.setCodigo(keyHolder.getKey().intValue());
	}
	
	@Override
	public void incluirEspecie(final Integer codigo, final OrdemServicoEspecie vo) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		update(new PreparedStatementCreator() {			
			@Override
			public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
				String sql = "INSERT INTO tb_ordem_servico_especie(cd_ordem_servico, id_tipo_especie, vl_especie, cd_banco, dc_cheque_agencia, dc_cheque_conta, dc_cheque_numero, dt_cheque) values(?,?,?,?,?,?,?,?)";
				PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

				ps.setInt(1, codigo);
				ps.setInt(2, vo.getFormaPagamento().getValue());
				ps.setDouble(3, vo.getValor());
				ps.setObject(4, vo.getBanco() != null ? vo.getBanco().getCodigo() : null);
				ps.setString(5, vo.getAgencia());
				ps.setString(6, vo.getConta());
				ps.setString(7, vo.getCheque());
				ps.setDate(8, vo.getDataCheque() != null ? new java.sql.Date(vo.getDataCheque().getTime()) : null);
				
			    return ps;
			}
		}, keyHolder);
		vo.setCodigo(keyHolder.getKey().intValue());
	}
	
	@Override
	public void associarDirecionamentoCheque(OrdemServicoEspecie especie, DirecionamentoCheque direcionamento) {
		String sql = "UPDATE tb_ordem_servico_especie set cd_direcionamento_cheque = ? WHERE cd_ordem_servico_especie = ?";
		update(sql, new Object[]{direcionamento.getCodigo(), especie.getCodigo()});
	}
	
	public ITurmaDAO getTurmaDAO() {
		return turmaDAO;
	}
	public void setTurmaDAO(ITurmaDAO turmaDAO) {
		this.turmaDAO = turmaDAO;
	}
	public IAgendamentoProvaDAO getAgendamentoProvaDAO() {
		return agendamentoProvaDAO;
	}
	public void setAgendamentoProvaDAO(IAgendamentoProvaDAO agendamentoProvaDAO) {
		this.agendamentoProvaDAO = agendamentoProvaDAO;
	}
	public IServicoDAO getServicoDAO() {
		return servicoDAO;
	}
	public void setServicoDAO(IServicoDAO servicoDAO) {
		this.servicoDAO = servicoDAO;
	}
	public IBancoDAO getBancoDAO() {
		return bancoDAO;
	}
	public void setBancoDAO(IBancoDAO bancoDAO) {
		this.bancoDAO = bancoDAO;
	}
	
}
